package mac5789.solver;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import mac5789.sat.SatProblem;
import mac5789.sat.SatProblemInput;

import org.apache.commons.io.IOUtils;

/**
 * Resolvedor que delega o serviço para o MiniSat
 * 
 * @author lundberg
 * 
 */
public class MiniSatSolver implements SatSolver {

    private static final String MINISAT_PATH = "MINISAT_PATH";

    private static final String DEFAULT_MINISAT_PATH = "bin/minisat";

    private MiniSatOutputParser outputParser = new MiniSatOutputParser();

    @Override
    public SatSolverResult solve(SatProblem problem) {
        try {
            File inputFile = File.createTempFile("problem", ".dimacs");
            inputFile.deleteOnExit();
            this.prepareInputFile(problem, inputFile);
            String command = this.getMiniSatPath() + " " + inputFile.getCanonicalPath();
            Process process = Runtime.getRuntime().exec(command);
            String output = IOUtils.toString(process.getInputStream());
            process.waitFor();
            process.destroy();
            inputFile.delete();
            return this.outputParser.parseOutput(output);
        } catch (IOException e) {
            throw new RuntimeException("Erro de IO inesperado durante resolução do problema.", e);
        } catch (InterruptedException e) {
            throw new RuntimeException("Operação cancelada.", e);
        }
    }

    private String getMiniSatPath() {
        return System.getProperty(MINISAT_PATH, DEFAULT_MINISAT_PATH);
    }

    private void prepareInputFile(SatProblem problem, File inputFile) throws FileNotFoundException, IOException {
        SatProblemInput input = null;
        FileOutputStream output = null;
        try {
            input = new SatProblemInput(problem);
            try {
                output = new FileOutputStream(inputFile);
                IOUtils.copy(input, output);
            } finally {
                IOUtils.closeQuietly(output);
            }
        } finally {
            IOUtils.closeQuietly(input);
        }
    }

}
